package org.lql.chaos.mq.rabbitmq.config;

import org.lql.chaos.mq.rabbitmq.constant.RabbitMQConstant;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Declarable;
import org.springframework.amqp.core.Declarables;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.ExchangeBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.QueueBuilder;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author: liangqinglong
 * @date: 2025-08-09 10:43
 * @description:
 **/
@Configuration
public class BusinessRetryConfig {

	// 重试阶梯（你可以按需改时长和层数）
	private static final List<Integer> RETRY_DELAYS_MS = Arrays.asList(
			5 * 1000,          // 1阶：5s
			30 * 1000         // 2阶：30s
	);

	public static final String HDR_RETRY_COUNT = "x-retry-count";
	public static final int MAX_RETRY = RETRY_DELAYS_MS.size();

	// 业务交换机
	@Bean(RabbitMQConstant.BUSINESS_EXCHANGE)
	public DirectExchange businessExchange() {
		return ExchangeBuilder.directExchange(RabbitMQConstant.BUSINESS_EXCHANGE).durable(true).build();
	}

	// 业务重试交换机
	@Bean(RabbitMQConstant.BUSINESS_RETRY_EXCHANGE)
	public DirectExchange businessRetryExchange() {
		return ExchangeBuilder.directExchange(RabbitMQConstant.BUSINESS_RETRY_EXCHANGE).durable(true).build();
	}

	// 业务队列
	@Bean(RabbitMQConstant.BUSINESS_QUEUE)
	public Queue businessQueue() {
		return new Queue(RabbitMQConstant.BUSINESS_QUEUE, true);
	}

	// 业务重试队列
	@Bean(RabbitMQConstant.BUSINESS_RETRY_QUEUE_PREFIX)
	public Queue businessRetryQueue() {
		return new Queue(RabbitMQConstant.BUSINESS_RETRY_QUEUE_PREFIX, true);
	}

	// 业务队列绑定业务交换机
	@Bean
	public Binding businessQueueBindingBusinessExchange(
			@Qualifier(RabbitMQConstant.BUSINESS_EXCHANGE) DirectExchange exchange,
			@Qualifier(RabbitMQConstant.BUSINESS_QUEUE) Queue queue
	) {
		return BindingBuilder.bind(queue).to(exchange).with(RabbitMQConstant.BUSINESS_ROUTING_KEY);
	}

	// === 关键点：按阶梯动态创建重试队列（TTL + DLX 回流到业务交换机） ===
	@Bean
	public Declarables retryQueuesAndBindings(
			@Qualifier(RabbitMQConstant.BUSINESS_RETRY_EXCHANGE) DirectExchange retryExchange
	) {
		List<Declarable> declarables = new ArrayList<>();

		for (int i = 1; i <= RETRY_DELAYS_MS.size(); i++) {
			int ttl = RETRY_DELAYS_MS.get(i - 1);

			String queueName = RabbitMQConstant.BUSINESS_RETRY_QUEUE_PREFIX + i;           // business.retry.queue.1
			String routingKey = RabbitMQConstant.BUSINESS_RETRY_ROUTING_KEY_PREFIX + i;    // business.retry.routing.key.1

			// 延迟队列：消息在这儿等 TTL，到期后通过 DLX 回到业务交换机（再进业务队列）
			Queue retryQueue = QueueBuilder.durable(queueName)
					.withArgument("x-max-length", 1000)
					.withArgument("x-dead-letter-exchange", RabbitMQConstant.BUSINESS_EXCHANGE)
					.withArgument("x-dead-letter-routing-key", RabbitMQConstant.BUSINESS_ROUTING_KEY)
					.withArgument("x-message-ttl", ttl)
					.build();

			Binding binding = BindingBuilder.bind(retryQueue).to(retryExchange).with(routingKey);

			declarables.add(retryQueue);
			declarables.add(binding);
		}

		return new Declarables(declarables);
	}

	// 提供计算下次路由 key 的工具方法
	public static String nextRetryRoutingKey(int nextRetryCount) {
		return RabbitMQConstant.BUSINESS_RETRY_ROUTING_KEY_PREFIX + nextRetryCount;
	}

	public static boolean hasMoreRetry(int currentRetryCount) {
		return currentRetryCount < MAX_RETRY;
	}

}
